#include <stdio.h>
# include <sys/types.h>
# include <sys/sem.h>
#include <stdlib.h>

static int lectores_escritores;
static int mutex;

int nuevo_sem(int llave, int num)
{
        int s;
        s = semget(llave, num, IPC_CREAT|0777);
        if (s < 0 ) {
                printf("Error creando semaforos");
                exit(0);
        }
        return s;
}
void esperar_sem(int s, int pos, int flag)
{
        struct sembuf sbuf;
        sbuf.sem_num = pos;
        sbuf.sem_op = -1;
        sbuf.sem_flg = flag;
        semop(s, &sbuf, 1);
}

void senalizar_sem(int s, int pos)
{
        struct sembuf sbuf;
        sbuf.sem_num = pos;
        sbuf.sem_op = 1;
        sbuf.sem_flg = 0;
        semop(s, &sbuf, 1);
}
void esperar_cero(int s, int pos)
{
        struct sembuf sbuf;
        sbuf.sem_num = pos;
        sbuf.sem_op = 0;
        sbuf.sem_flg = 0;
        semop(s, &sbuf, 1);
}
/*inicializar_sem*/
void inicializar_sem(int s, int valor)
{
        semctl(s, 0, SETVAL, valor);
}
void eliminar_sem(int s)
{
        int rem = semctl(s, 0, IPC_RMID, 0);
        if (rem<0){
        printf("Error eliminando semaforo %d...\n",s);
        exit(0);
        }
        printf("Semaforo eliminado #%d\n",s);
}
void inicializar_le()
{
        int clave = 50;
        int sarg_array[] = {0, 0};
        int sarg = 1;
        lectores_escritores = nuevo_sem(clave, 2);
        // [0] = escritores
        // [1] = lectores
        semctl(lectores_escritores, 0, SETALL, sarg_array);
        mutex = nuevo_sem(clave+1, 1);

       semctl(mutex, 0, SETVAL, sarg);
}
void eliminar_le()
{
       int rem = semctl(lectores_escritores,0,IPC_RMID,0);
       if (rem < 0) {
       printf("Error eliminando semaforos...\n");
       exit(0);
       }
       rem = semctl(mutex,0,IPC_RMID,0);
       if (rem < 0) {
       printf("Error eliminando semaforos...\n");
       exit(0);
       }
}
void entrada_lectores()
{
       struct sembuf sbuf[2];
       // [0] = escritores
       // [1] = lectores
       // wait for zero escritores
       sbuf[0].sem_num = 0;
       sbuf[0].sem_op = 0;
       sbuf[0].sem_flg = 0;
       // senalizar lectores
       sbuf[1].sem_num = 1;
       sbuf[1].sem_op = 1;
       sbuf[1].sem_flg = 0;
       semop(lectores_escritores, sbuf, 2);
}
void salida_lectores()
{
       esperar_sem(lectores_escritores, 1, 0);
}
void entrada_escritores()
{
       // senalizar escritores
       senalizar_sem(lectores_escritores, 0);
       // esperar 0 de lectores
       esperar_cero(lectores_escritores, 1);
       esperar_sem(mutex, 0, SEM_UNDO);
}
void salida_escritores()
{
       senalizar_sem(mutex, 0);
       esperar_sem(lectores_escritores, 0, 0);
}

